package com.yhn.shortlink.project.utils;

import cn.hutool.core.lang.hash.MurmurHash;


/**哈希工具类
 * @author yhnyhn123
 */
public class HashUtil {

    private static final char[] CHARS = new char[]{
            '0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
            'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z',
            'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'
    };

    private static final int SIZE = CHARS.length;

    /**
     * 将十进制数转换为62进制表示的字符串。
     * 该方法通过不断地对62取余和除以62，将十进制数转换为62进制数。
     * 使用字符数组CHARS作为62进制数的符号集，包含0-9，A-Z，a-z共62个字符。
     * @param num 需要转换的十进制数。
     * @return 转换后的62进制字符串。
     */
    private static String convertDecToBase62(long num) {
        // 使用StringBuilder来构建结果字符串，因为它比String拼接效率更高。
        StringBuilder sb = new StringBuilder();
        // 当num大于0时，循环继续，表示还有余数可以取出。
        while (num > 0) {
            // 取出num对62的余数，得到的数在0-61之间。
            int i = (int) (num % SIZE);
            // 将余数对应的字符追加到结果字符串中。
            sb.append(CHARS[i]);
            // 将num除以62，为下一轮循环做准备。
            num /= SIZE;
        }

        // 由于追加字符的顺序是从低位到高位，而实际需要的顺序是从高位到低位，因此需要反转字符串。
        return sb.reverse().toString();
    }


    /**
     * 将给定的字符串转换为Base62编码的字符串。
     * 使用MurmurHash算法对字符串进行哈希处理，然后将得到的哈希值转换为Base62编码。
     * 这种方法适用于生成唯一标识或短链接等场景。
     * @param str 待转换的字符串
     * @return Base62编码后的字符串
     */
    public static String hashToBase62(String str) {
        // 使用MurmurHash算法计算字符串的哈希值
        int i = MurmurHash.hash32(str);

        // 将哈希值转换为非负数，以适应Base62编码的需求
        // 如果哈希值为负数，则将其转换为对应的正数，使用Integer.MAX_VALUE进行调整
        long num = i < 0 ? Integer.MAX_VALUE - (long) i : i;

        // 调用convertDecToBase62方法，将转换后的数字转换为Base62编码的字符串
        return convertDecToBase62(num);
    }

}
